/**
 * IndexedDB管理器 - 用于缓存GLTF模型和纹理数据
 */
export class IndexedDBManager {
    constructor() {
        this.dbName = 'Kokomi3D_ModelCache';
        this.dbVersion = 1;
        this.db = null;
        this.storeName = 'models';
        this.textureStoreName = 'textures';
        this.metadataStoreName = 'metadata';
    }
    
    /**
     * 初始化IndexedDB
     * @returns {Promise<IDBDatabase>}
     */
    async init() {
        if (this.db) return this.db;
        
        return new Promise((resolve, reject) => {
            const request = indexedDB.open(this.dbName, this.dbVersion);
            
            request.onerror = () => {
                console.error('IndexedDB初始化失败:', request.error);
                reject(request.error);
            };
            
            request.onsuccess = () => {
                this.db = request.result;
                console.log('IndexedDB初始化成功');
                resolve(this.db);
            };
            
            request.onupgradeneeded = (event) => {
                const db = event.target.result;
                
                // 创建模型存储
                if (!db.objectStoreNames.contains(this.storeName)) {
                    const modelStore = db.createObjectStore(this.storeName, { keyPath: 'id' });
                    modelStore.createIndex('url', 'url', { unique: false });
                    modelStore.createIndex('timestamp', 'timestamp', { unique: false });
                    console.log('创建模型存储');
                }
                
                // 创建纹理存储
                if (!db.objectStoreNames.contains(this.textureStoreName)) {
                    const textureStore = db.createObjectStore(this.textureStoreName, { keyPath: 'id' });
                    textureStore.createIndex('modelId', 'modelId', { unique: false });
                    console.log('创建纹理存储');
                }
                
                // 创建元数据存储
                if (!db.objectStoreNames.contains(this.metadataStoreName)) {
                    const metadataStore = db.createObjectStore(this.metadataStoreName, { keyPath: 'key' });
                    console.log('创建元数据存储');
                }
            };
        });
    }
    
    /**
     * 缓存GLTF模型数据
     * @param {string} modelId - 模型ID
     * @param {string} url - 模型URL
     * @param {ArrayBuffer} data - 模型数据
     * @param {Object} metadata - 元数据
     * @returns {Promise<void>}
     */
    async cacheModel(modelId, url, data, metadata = {}) {
        await this.init();
        
        const modelData = {
            id: modelId,
            url: url,
            data: data,
            metadata: metadata,
            timestamp: Date.now(),
            size: data.byteLength
        };
        
        return new Promise((resolve, reject) => {
            const transaction = this.db.transaction([this.storeName], 'readwrite');
            const store = transaction.objectStore(this.storeName);
            const request = store.put(modelData);
            
            request.onsuccess = () => {
                console.log(`模型 ${modelId} 已缓存到IndexedDB`);
                resolve();
            };
            
            request.onerror = () => {
                console.error(`缓存模型 ${modelId} 失败:`, request.error);
                reject(request.error);
            };
        });
    }
    
    /**
     * 从缓存中获取模型数据
     * @param {string} modelId - 模型ID
     * @returns {Promise<Object|null>} 模型数据
     */
    async getModel(modelId) {
        await this.init();
        
        return new Promise((resolve, reject) => {
            const transaction = this.db.transaction([this.storeName], 'readonly');
            const store = transaction.objectStore(this.storeName);
            const request = store.get(modelId);
            
            request.onsuccess = () => {
                const result = request.result;
                if (result) {
                    console.log(`从缓存中获取模型 ${modelId}`);
                    resolve(result);
                } else {
                    resolve(null);
                }
            };
            
            request.onerror = () => {
                console.error(`获取模型 ${modelId} 失败:`, request.error);
                reject(request.error);
            };
        });
    }
    
    /**
     * 检查模型是否已缓存
     * @param {string} modelId - 模型ID
     * @returns {Promise<boolean>}
     */
    async hasModel(modelId) {
        const model = await this.getModel(modelId);
        return model !== null;
    }
    
    /**
     * 删除缓存的模型
     * @param {string} modelId - 模型ID
     * @returns {Promise<void>}
     */
    async deleteModel(modelId) {
        await this.init();
        
        return new Promise((resolve, reject) => {
            const transaction = this.db.transaction([this.storeName], 'readwrite');
            const store = transaction.objectStore(this.storeName);
            const request = store.delete(modelId);
            
            request.onsuccess = () => {
                console.log(`模型 ${modelId} 已从缓存中删除`);
                resolve();
            };
            
            request.onerror = () => {
                console.error(`删除模型 ${modelId} 失败:`, request.error);
                reject(request.error);
            };
        });
    }
    
    /**
     * 获取所有缓存的模型列表
     * @returns {Promise<Array>} 模型列表
     */
    async getAllModels() {
        await this.init();
        
        return new Promise((resolve, reject) => {
            const transaction = this.db.transaction([this.storeName], 'readonly');
            const store = transaction.objectStore(this.storeName);
            const request = store.getAll();
            
            request.onsuccess = () => {
                resolve(request.result);
            };
            
            request.onerror = () => {
                console.error('获取所有模型失败:', request.error);
                reject(request.error);
            };
        });
    }
    
    /**
     * 缓存纹理数据
     * @param {string} textureId - 纹理ID
     * @param {string} modelId - 所属模型ID
     * @param {ArrayBuffer} data - 纹理数据
     * @param {string} mimeType - MIME类型
     * @returns {Promise<void>}
     */
    async cacheTexture(textureId, modelId, data, mimeType) {
        await this.init();
        
        const textureData = {
            id: textureId,
            modelId: modelId,
            data: data,
            mimeType: mimeType,
            timestamp: Date.now(),
            size: data.byteLength
        };
        
        return new Promise((resolve, reject) => {
            const transaction = this.db.transaction([this.textureStoreName], 'readwrite');
            const store = transaction.objectStore(this.textureStoreName);
            const request = store.put(textureData);
            
            request.onsuccess = () => {
                console.log(`纹理 ${textureId} 已缓存`);
                resolve();
            };
            
            request.onerror = () => {
                console.error(`缓存纹理 ${textureId} 失败:`, request.error);
                reject(request.error);
            };
        });
    }
    
    /**
     * 获取缓存的纹理
     * @param {string} textureId - 纹理ID
     * @returns {Promise<Object|null>} 纹理数据
     */
    async getTexture(textureId) {
        await this.init();
        
        return new Promise((resolve, reject) => {
            const transaction = this.db.transaction([this.textureStoreName], 'readonly');
            const store = transaction.objectStore(this.textureStoreName);
            const request = store.get(textureId);
            
            request.onsuccess = () => {
                resolve(request.result || null);
            };
            
            request.onerror = () => {
                console.error(`获取纹理 ${textureId} 失败:`, request.error);
                reject(request.error);
            };
        });
    }
    
    /**
     * 清理过期的缓存数据
     * @param {number} maxAge - 最大缓存时间（毫秒）
     * @returns {Promise<number>} 清理的项目数量
     */
    async cleanup(maxAge = 7 * 24 * 60 * 60 * 1000) { // 默认7天
        await this.init();
        
        const cutoffTime = Date.now() - maxAge;
        let cleanedCount = 0;
        
        // 清理模型
        const models = await this.getAllModels();
        for (const model of models) {
            if (model.timestamp < cutoffTime) {
                await this.deleteModel(model.id);
                cleanedCount++;
            }
        }
        
        // 清理纹理
        const textures = await this.getAllTextures();
        for (const texture of textures) {
            if (texture.timestamp < cutoffTime) {
                await this.deleteTexture(texture.id);
                cleanedCount++;
            }
        }
        
        console.log(`清理了 ${cleanedCount} 个过期缓存项`);
        return cleanedCount;
    }
    
    /**
     * 获取所有缓存的纹理
     * @returns {Promise<Array>} 纹理列表
     */
    async getAllTextures() {
        await this.init();
        
        return new Promise((resolve, reject) => {
            const transaction = this.db.transaction([this.textureStoreName], 'readonly');
            const store = transaction.objectStore(this.textureStoreName);
            const request = store.getAll();
            
            request.onsuccess = () => {
                resolve(request.result);
            };
            
            request.onerror = () => {
                console.error('获取所有纹理失败:', request.error);
                reject(request.error);
            };
        });
    }
    
    /**
     * 删除纹理
     * @param {string} textureId - 纹理ID
     * @returns {Promise<void>}
     */
    async deleteTexture(textureId) {
        await this.init();
        
        return new Promise((resolve, reject) => {
            const transaction = this.db.transaction([this.textureStoreName], 'readwrite');
            const store = transaction.objectStore(this.textureStoreName);
            const request = store.delete(textureId);
            
            request.onsuccess = () => {
                resolve();
            };
            
            request.onerror = () => {
                reject(request.error);
            };
        });
    }
    
    /**
     * 获取缓存统计信息
     * @returns {Promise<Object>} 统计信息
     */
    async getStatistics() {
        await this.init();
        
        const [models, textures] = await Promise.all([
            this.getAllModels(),
            this.getAllTextures()
        ]);
        
        const modelSize = models.reduce((total, model) => total + (model.size || 0), 0);
        const textureSize = textures.reduce((total, texture) => total + (texture.size || 0), 0);
        
        return {
            modelCount: models.length,
            textureCount: textures.length,
            totalSize: modelSize + textureSize,
            modelSize: modelSize,
            textureSize: textureSize,
            formattedSize: this.formatBytes(modelSize + textureSize)
        };
    }
    
    /**
     * 格式化字节大小
     * @param {number} bytes - 字节数
     * @returns {string} 格式化后的大小
     */
    formatBytes(bytes) {
        if (bytes === 0) return '0 Bytes';
        
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }
    
    /**
     * 清空所有缓存
     * @returns {Promise<void>}
     */
    async clearAll() {
        await this.init();
        
        const transaction = this.db.transaction([this.storeName, this.textureStoreName], 'readwrite');
        
        await Promise.all([
            new Promise((resolve, reject) => {
                const request = transaction.objectStore(this.storeName).clear();
                request.onsuccess = () => resolve();
                request.onerror = () => reject(request.error);
            }),
            new Promise((resolve, reject) => {
                const request = transaction.objectStore(this.textureStoreName).clear();
                request.onsuccess = () => resolve();
                request.onerror = () => reject(request.error);
            })
        ]);
        
        console.log('所有缓存已清空');
    }
    
    /**
     * 关闭数据库连接
     */
    close() {
        if (this.db) {
            this.db.close();
            this.db = null;
            console.log('IndexedDB连接已关闭');
        }
    }
}
